/*!
 * @brief task.c
 * @author scpsyl
 */
#include "task.h"
#include "main.h"
#include "tim.h"
#include "lcd1602.h"


#define WASHING_TIMES 100
#define RINSING_TIMES 50
#define  DRYING_TIMES 30

work_state state = INIT;
work_mode mode = START;
const char* work_state_strings[] = {
#define X(state, str) str,
        WORK_STATE_LIST
#undef X
};

const char* work_mode_strings[] = {
#define X(mode, str) str,
        WORK_MODE_LIST
#undef X
};
//Internal Declaration
void Task_SetState(work_state _state);
void Task_SetMode(work_mode _mode);
void Task_JudgeState();
void Task_JudgeMode();
void Task_ChooseMode();
void Task_WaterInput();
void Task_WaterOutput();
void Task_Washing();
void Task_Rinsing();
void Task_Drying();
void Task_IDLE();
void Task_StateShow();
void Test_Mode_();

/*!
 * @details 对应洗衣机五种模式的内部声明
 */
void Task_Standard();
void Task_Fast();
void Task_Heavy();
void Task_DrySingle();
void Task_Clean();

/*!
 * @brief 测试函数
 */
void Test_State(work_state _state);
void Test_Mode();

typedef void (*task_func_t)(void);
typedef void (*mode_func_t)(void);

task_func_t task_functions[] = {
        Task_ChooseMode,     // INIT
        Task_WaterInput,     // WATER_INPUT
        Task_WaterOutput,    // WATER_OUTPUT
        Task_Washing,        // WASHING
        Task_Rinsing,        // RINSING
        Task_Drying          // DRYING
};
mode_func_t mode_functions[]={
        Task_Standard,
        Task_Fast,
        Task_Heavy,
        Task_DrySingle,
        Task_Clean
};


/*!
 * @brief  手动设置状态
 * @details 测试程序用于验证 发行后注释
 * @param _state
 */
void Task_SetState(work_state _state)
{
    state = _state;
}
void Task_SetMode(work_mode _mode) {
    mode = _mode;
}
/*!
 * @brief
 */
void Task_Perform()
{
    Test_Mode();
}
void Test_State(work_state _state)
{
    Task_SetState(_state);
    Task_StateShow();
    Task_JudgeState();
}
void Test_Mode()
{
    Task_SetMode(SINGLE_DRY);
    //Test_Mode_();
    Task_JudgeMode();
    Task_StateShow();
}

void Task_JudgeState()
{
    if (state >= INIT && state <= DRYING) {
        task_func_t task_func = task_functions[state];
        if (task_func != NULL) {
            task_func();
        }
    }
}

void Task_JudgeMode()
{
    if (mode >= START && mode <= CLEAN) {
        mode_func_t  mode_func = mode_functions[mode - 1];
        if (mode_func != NULL) {
            mode_func();
        }
    }
}

/*!
 * @details 通过按键选择对应工作状态 预置了5个模式
 */
void Task_ChooseMode()
{
    uint8_t  isEN = 0;
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)){
        isEN = 1;
    }
    if(isEN == 1){
        isEN = 0;
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1))
        {
            HAL_Delay(20);
            if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)){
                mode = STANDARD;
                //HAL_UART_Transmit(&huart1,"STANDARD\r\n",10,0xfff);
            }
        }
        else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2))
        {
            HAL_Delay(20);
            if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2))
                mode = FAST;
        }
        else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3))
        {
            HAL_Delay(20);
            if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3))
                mode = HEAVY;
        }
        else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4))
        {
            HAL_Delay(20);
            if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4))
                mode = SINGLE_DRY;
        }
        else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6))
        {
            HAL_Delay(20);
            if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6))
                mode = CLEAN;
        }

    }

}
void Test_Mode_()
{
    if(HAL_GPIO_ReadPin(STANDARD_GPIO_Port,STANDARD_Pin))
    {
        HAL_Delay(20);
        if(HAL_GPIO_ReadPin(STANDARD_GPIO_Port,STANDARD_Pin)){
            mode = STANDARD;
            //HAL_UART_Transmit(&huart1,"STANDARD\r\n",10,0xfff);
        }
    }
    else if(HAL_GPIO_ReadPin(FAST_GPIO_Port,FAST_Pin))
    {
        HAL_Delay(20);
        if(HAL_GPIO_ReadPin(FAST_GPIO_Port,FAST_Pin))
            mode = FAST;
    }
    else if(HAL_GPIO_ReadPin(HEAVY_GPIO_Port,HEAVY_Pin))
    {
        HAL_Delay(20);
        if(HAL_GPIO_ReadPin(HEAVY_GPIO_Port,HEAVY_Pin))
            mode = HEAVY;
    }
    else if(HAL_GPIO_ReadPin(SINGLE_DRY_GPIO_Port,SINGLE_DRY_Pin))
    {
        HAL_Delay(20);
        if(HAL_GPIO_ReadPin(SINGLE_DRY_GPIO_Port,SINGLE_DRY_Pin))
            mode = SINGLE_DRY;
    }
    else if(HAL_GPIO_ReadPin(CLEAN_GPIO_Port,CLEAN_Pin))
    {
        HAL_Delay(20);
        if(HAL_GPIO_ReadPin(CLEAN_GPIO_Port,CLEAN_Pin))
            mode = CLEAN;
    }
    else
        mode = START;
}

/*!
 * @details 指示灯状态显示
 */
 void Task_StateShowInit()
{
    HAL_GPIO_WritePin(GPIOA,INPUT_Pin|OUTPUT_Pin,1);
    HAL_GPIO_WritePin(GPIOB,RGB_R_Pin|RGB_G_Pin|RGB_B_Pin,1);
}
void Task_StateShow()
{
    Task_StateShowInit();
    switch (state) {
        case WATER_INPUT:
        case WATER_OUTPUT:
            //指示灯闪烁 表示进出水
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
            HAL_Delay(20);
            break;
        case WASHING:
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,0);
            //HAL_UART_Transmit(&huart1,"WASHING\r\n",9,0xfff);
            break;
        case RINSING:
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);
            break;
        case DRYING:
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);
            break;
        default:
            break;
    }
}
/*!
 * @details TIM1_CH1&2 对应进出水电机
 */
 //把显示部分和执行部分结合
void Task_WaterInput(){
    state = WATER_INPUT;
     LCD_Puts(0,1,"Input    ");
     LCD_Puts(9,1,"Temp:19");
     HAL_GPIO_WritePin(INPUT_GPIO_Port, INPUT_Pin,0);
    //HAL_UART_Transmit(&huart1,"WATER\r\n",7,0xfff);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,10000-2);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,1);
    HAL_Delay(3000);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,1);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,1);
     HAL_GPIO_WritePin(INPUT_GPIO_Port, INPUT_Pin,1);
}
void Task_WaterOutput(){
    state = WATER_OUTPUT;
    LCD_Puts(0,1,"Output   ");
    LCD_Puts(9,1,"Temp:19");
    HAL_GPIO_WritePin(OUTPUT_GPIO_Port, OUTPUT_Pin,0);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,1);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,10000-2);
    HAL_Delay(3000);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,1);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,1);
    HAL_GPIO_WritePin(OUTPUT_GPIO_Port, OUTPUT_Pin,1);
}

/*!
 * @details 每个洗涤段持续10min 期间电机持续10次启停
 *          洗涤电机保持70%转速
 */
void Task_Washing()
{
    state = WASHING;

    LCD_Puts(0,1,"Washing  ");
    LCD_Puts(9,1,"Temp:29");
    HAL_GPIO_WritePin(RGB_R_GPIO_Port,RGB_R_Pin,0);
    for(uint8_t i = 0;i<WASHING_TIMES;i++){
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,7000);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(2);
    }
    for(uint8_t i = 0;i<WASHING_TIMES; i++){
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,7000);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(2);
    }
    HAL_GPIO_WritePin(RGB_R_GPIO_Port,RGB_R_Pin,1);
}
void Task_Rinsing()
{
//    此处设置温度
    state = RINSING;

    LCD_Puts(0,1,"Rinsing  ");
    LCD_Puts(9,1,"Temp:39");
    HAL_GPIO_WritePin(RGB_G_GPIO_Port,RGB_G_Pin,0);
    for(uint8_t i = 0;i<RINSING_TIMES;i++) {
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 4000);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 0);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 0);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 0);
        HAL_Delay(2);
    }
    for(uint8_t i = 0;i<RINSING_TIMES; i++){
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,4000);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(2);
    }
    HAL_GPIO_WritePin(RGB_G_GPIO_Port,RGB_G_Pin,1);
}
void Task_Drying()
{
    state = DRYING;

    LCD_Puts(0,1,"Drying   ");
    LCD_Puts(9,1,"Temp:29");
    HAL_GPIO_WritePin(RGB_B_GPIO_Port,RGB_B_Pin,0);
    for(uint8_t i = 0;i<DRYING_TIMES;i++) {
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 10000 - 1);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 0);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 0);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 0);
        HAL_Delay(2);
    }
    for(uint8_t i = 0;i<DRYING_TIMES; i++){
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,10000-1);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(2);
    }
    HAL_GPIO_WritePin(RGB_B_GPIO_Port,RGB_B_Pin,1);
}
//一个倒计时
void LCD_Time()
{
    LCD_Puts(15,0,"5");
    HAL_Delay(500);
    LCD_Puts(15,0,"4");
    HAL_Delay(500);
    LCD_Puts(15,0,"3");
    HAL_Delay(500);
    LCD_Puts(15,0,"2");
    HAL_Delay(500);
    LCD_Puts(15,0,"1");
    HAL_Delay(500);
    LCD_Puts(15,0," ");
}
/*!
 * @brief 标准洗
 * @details 两次进水 一次清洗 两次漂洗  一次甩干
 */
void Task_Standard()
{
    mode = STANDARD;
    LCD_Clear();
    LCD_Puts(0,0,"STANDARD");
    //加一个倒计时
    LCD_Time();
    //初始进水
    Task_WaterInput();
    HAL_Delay(1000);
    //清洗一次
    Task_Washing();
    HAL_Delay(1000);
    Task_WaterOutput();
    Task_Drying();
    //漂洗两次
    for(uint8_t i = 0;i < 2;i++)
    {
        Task_WaterInput();
        HAL_Delay(1000);
        Task_Rinsing();
        HAL_Delay(1000);
        Task_WaterOutput();
        Task_Drying();
    }
    //一次甩干
    Task_WaterOutput();
    Task_Drying();
    LCD_Puts(0,1,"OK!!");
}
void Task_Fast()
{
    mode = FAST;
    LCD_Clear();
    LCD_Puts(0,0,"FAST");
    LCD_Time();
    //初始进水
    Task_WaterInput();
    HAL_Delay(1000);
    //洗一次
    Task_Washing();
    HAL_Delay(1000);
    Task_WaterOutput();
    Task_Drying();
    //漂一次
    Task_WaterInput();
    HAL_Delay(1000);
    Task_Rinsing();
    HAL_Delay(1000);
    //甩一次
    Task_WaterOutput();
    Task_Drying();
    //完事
    LCD_Clear();
    LCD_Puts(0,1,"OK!!");
}

void Task_Heavy()
{
    mode = HEAVY;
    LCD_Clear();
    LCD_Puts(0,0,"HEAVY");
    LCD_Time();
    //初始进水
    Task_WaterInput();
    HAL_Delay(1000);
    //洗漂洗漂洗
    //洗一次
    Task_Washing();
    HAL_Delay(1000);
    Task_WaterOutput();
    Task_Drying();
    //漂一次
    Task_WaterInput();
    HAL_Delay(1000);
    Task_Rinsing();
    HAL_Delay(1000);
    Task_WaterOutput();
    Task_Drying();
    Task_WaterInput();
    HAL_Delay(1000);
    //洗2次
    Task_Washing();
    HAL_Delay(1000);
    Task_WaterOutput();
    Task_Drying();
    //漂2次
    Task_WaterInput();
    HAL_Delay(1000);
    Task_Rinsing();
    HAL_Delay(1000);
    //甩
    Task_WaterOutput();
    Task_Drying();
    //完事
    LCD_Clear();
    LCD_Puts(0,1,"OK!!");

}
void Task_DrySingle()
{
    mode = SINGLE_DRY;
    LCD_Clear();
    LCD_Puts(0,0,"SINGLE_DRY");
    LCD_Time();
    Task_WaterOutput();
    for(uint8_t i = 0;i < 3;i++)
    {
        Task_Drying();
    }
    //完事
    LCD_Clear();
    LCD_Puts(0,1,"OK!!");
}
/*!
 * 桶自洁温度专供函数
 */
void Task_WaterInputForClean(){
    state = WATER_INPUT;
    LCD_Puts(0,1,"Input    ");
    LCD_Puts(9,1,"Temp:39");
    HAL_GPIO_WritePin(INPUT_GPIO_Port, INPUT_Pin,0);
    //HAL_UART_Transmit(&huart1,"WATER\r\n",7,0xfff);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,10000-2);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,1);
    HAL_Delay(3000);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,1);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,1);
    HAL_GPIO_WritePin(INPUT_GPIO_Port, INPUT_Pin,1);
}
void Task_WaterOutputForClean(){
    state = WATER_OUTPUT;
    LCD_Puts(0,1,"Output   ");
    LCD_Puts(9,1,"Temp:39");
    HAL_GPIO_WritePin(OUTPUT_GPIO_Port, OUTPUT_Pin,0);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,1);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,10000-2);
    HAL_Delay(3000);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,1);
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,1);
    HAL_GPIO_WritePin(OUTPUT_GPIO_Port, OUTPUT_Pin,1);
}

/*!
 * @details 每个洗涤段持续10min 期间电机持续10次启停
 *          洗涤电机保持70%转速
 */
void Task_WashingForClean()
{
    state = WASHING;

    LCD_Puts(0,1,"Washing  ");
    LCD_Puts(9,1,"Temp:59");
    HAL_GPIO_WritePin(RGB_R_GPIO_Port,RGB_R_Pin,0);
    for(uint8_t i = 0;i<WASHING_TIMES;i++){
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,7000);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(2);
    }
    for(uint8_t i = 0;i<WASHING_TIMES; i++){
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,7000);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(2);
    }
    HAL_GPIO_WritePin(RGB_R_GPIO_Port,RGB_R_Pin,1);
}
void Task_RinsingForClean()
{
//    此处设置温度
    state = RINSING;

    LCD_Puts(0,1,"Rinsing  ");
    LCD_Puts(9,1,"Temp:59");
    HAL_GPIO_WritePin(RGB_G_GPIO_Port,RGB_G_Pin,0);
    for(uint8_t i = 0;i<RINSING_TIMES;i++) {
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 4000);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 0);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 0);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 0);
        HAL_Delay(2);
    }
    for(uint8_t i = 0;i<RINSING_TIMES; i++){
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,4000);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(2);
    }
    HAL_GPIO_WritePin(RGB_G_GPIO_Port,RGB_G_Pin,1);
}
void Task_DryingForClean()
{
    state = DRYING;

    LCD_Puts(0,1,"Drying   ");
    LCD_Puts(9,1,"Temp:59");
    HAL_GPIO_WritePin(RGB_B_GPIO_Port,RGB_B_Pin,0);
    for(uint8_t i = 0;i<DRYING_TIMES;i++) {
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 10000 - 1);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 0);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 0);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 0);
        HAL_Delay(2);
    }
    for(uint8_t i = 0;i<DRYING_TIMES; i++){
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,10000-1);
        HAL_Delay(28);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
        __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,0);
        HAL_Delay(2);
    }
    HAL_GPIO_WritePin(RGB_B_GPIO_Port,RGB_B_Pin,1);
}
//桶自洁 温度给高
void Task_Clean()
{
    mode = CLEAN;
    LCD_Clear();
    LCD_Puts(0,0,"CLEAN");
    LCD_Time();
    //初始进水
    Task_WaterInputForClean();
    HAL_Delay(1000);
    for(uint8_t i = 0;i < 3;i++)
    {
        Task_WashingForClean();
        HAL_Delay(1000);
        Task_WaterOutputForClean();
        Task_DryingForClean();
    }
    //甩一次
    Task_WaterOutputForClean();
    Task_DryingForClean();
    //完事
    LCD_Clear();
    LCD_Puts(0,1,"OK!!");
}





